const express = require("express");
const router = express.Router();
const _ = require("lodash");
const path = require("path");
const dirname = path.resolve();
const { Entity, validateEntity } = require(path.join(
  dirname,
  "src/model/entity"
));
const { Mapping, validateMapping } = require(path.join(
  dirname,
  "src/model/mapping"
));
const { Storage } = require(path.join(dirname, "src/model/storage"));

function handleEntityJSON(entity, fn) {
  const entityTemp = _.pick(entity, [
    "_id",
    "entityName",
    "description",
    "owners",
    "fields",
    "indexs",
  ]);
  entityTemp.fields = fn(entityTemp.fields);
  entityTemp.indexs = fn(entityTemp.indexs);
  return entityTemp;
}

function handleMappingJSON(mapping, fn) {
  const mappingTemp = _.pick(mapping, [
    "_id",
    "entityName",
    "storageUri",
    "tableName",
    "idcs",
    "columns",
  ]);
  if (mappingTemp.columns) {
    mappingTemp.columns = fn(mappingTemp.columns);
  }
  return mappingTemp;
}

function handleStorageJSON(storage) {
  const storageTemp = _.pick(storage, [
    "_id",
    "storageUri",
    "description",
    "idcInfos",
    "type",
    "owners",
  ]);
  storageTemp.idcInfos = JSON.parse(storageTemp.idcInfos);
  return storageTemp;
}

// 获取 entity 数据列表
router.get("/", async (req, res) => {
  req.query = _.pick(req.query, [
    "query",
    "owner",
    "storageUri",
    "first",
    "number",
  ]);
  const { query, owner, storageUri } = req.query;

  const queryReg = new RegExp(query, "gi");
  const ownersReg = new RegExp(owner, "gi");

  const skip = req.query.first || 1;
  const limit = req.query.number || 100;

  let entitys = [];
  if (!storageUri) {
    entitys = await Entity.find({ entityName: queryReg, owners: ownersReg })
      .skip(skip - 1)
      .limit(limit)
      .sort({ modifyTime: -1 });
  } else {
    const mapping = await Mapping.find({ storageUri })
      .populate("entity")
      .exec();
    mapping.forEach((item) => {
      if (
        queryReg.test(item.entity.entityName) &&
        ownersReg.test(item.entity.owner)
      ) {
        entitys.push(item.entity);
      }
    });
  }

  const result = entitys.map((item) => handleEntityJSON(item, JSON.parse));
  res.send({ data: result, message: "获取 entity 成功" });
});

// 根据 entityName 获取详细信息
router.get("/:entityName", async (req, res) => {
  const mapping = await Mapping.findOne({ entityName: req.params.entityName })
    .populate("entity")
    .populate("storage")
    .exec();
  if (!mapping) return res.status(400).send({ message: "该 entity 不存在" });
  const result = handleEntityJSON(mapping.entity, JSON.parse);
  result.mapping = handleMappingJSON(mapping, JSON.parse);
  result.storage = handleStorageJSON(mapping.storage, JSON.parse);
  res.send({ data: result, message: "获取 entity 成功" });
});

// 创建 entity, mapping
router.post("/add", async (req, res) => {
  const entity = handleEntityJSON(req.body.entity, JSON.stringify);
  const mapping = handleMappingJSON(req.body.mapping, JSON.stringify);

  const { error: entityError } = validateEntity(entity);
  if (entityError)
    return res.status(400).send({ message: entityError.message });
  const { error: mappingError } = validateMapping(mapping);
  if (mappingError)
    return res.status(400).send({ message: mappingError.message });

  // 查询该 entity 是否存在
  const entityTemp = await Entity.findOne({ entityName: entity.entityName });
  if (entityTemp)
    return res.status(400).send({ message: "该 entity 已经存在" });

  // 添加 entity, mapping
  const entityData = await new Entity(entity).save();
  const storageData = await Storage.findOne({ storageUri: mapping.storageUri });
  await new Mapping({
    ...mapping,
    entity: entityData._id,
    storage: storageData._id,
  }).save();

  res.send({
    message: "创建 entity 成功",
  });
});

// 编辑 entity, mapping
router.put("/:entityName", async (req, res) => {
  const entity = handleEntityJSON(req.body.entity, JSON.stringify);
  const mapping = handleMappingJSON(req.body.mapping, JSON.stringify);

  const { error: entityError } = validateEntity(entity);
  if (entityError)
    return res.status(400).send({ message: entityError.message });
  const { error: mappingError } = validateMapping(mapping);
  if (mappingError)
    return res.status(400).send({ message: mappingError.message });

  // 查询该 entity 是否存在
  const entityTemp = await Entity.findOne({ entityName: entity.entityName });
  if (!entityTemp) return res.status(400).send({ message: "该 entity 不存在" });

  // 编辑 entity, mapping
  await Entity.findByIdAndUpdate(
    entityTemp._id,
    { $set: entity },
    { useFindAndModify: false }
  );

  let storageId;
  const mappingTemp = await Mapping.findOne({ entityName: entity.entityName });
  if (mappingTemp.storageUri !== mapping.storageUri) {
    storageId = await Storage.findOne({ storageUri: mapping.storageUri })
      .storage;
  } else {
    storageId = mappingTemp.storage;
  }
  await Mapping.findByIdAndUpdate(
    mappingTemp._id,
    { $set: { ...mapping, storage: storageId } },
    { useFindAndModify: false }
  );

  res.send({
    message: "编辑 entity 成功",
  });
});

// 根据 entityName 删除 entity
router.delete("/:entityName", async (req, res) => {
  // 查询该 entityName 是否存在
  const entity = await Entity.findOne({ entityName: req.params.entityName });
  if (!entity) return res.status(400).send({ message: "该 entity 不存在" });

  // 编辑 entity
  await Entity.findByIdAndDelete(entity._id);
  res.send({
    message: "删除 entity 成功",
  });
});

module.exports = router;
